/*
 * apidoc
 * https://apidocjs.com
 *
 * Copyright (c) 2013 inveris OHG
 * Authors: Peter Rottmann <rottmann@inveris.de>
 * Nicolas CARPi @ Deltablot
 * Licensed under the MIT license.
 */

/**
 * Write output files
 */
class Writer {
  constructor(api, app, cacheBustingQueryParam = `v=${Date.now()}`) {
    this.api = api;
    this.log = app.log;
    this.opt = app.options;
    this.cacheBustingQueryParam = String(cacheBustingQueryParam);
    this.fs = require("fs-extra");
    this.path = require("path");
  }

  // The public method
  write() {
    if (this.opt.dryRun) {
      this.log.info("Dry run mode enabled: no files created.");
      return new Promise((resolve, reject) => {
        return resolve();
      });
    }

    this.log.verbose("Writing files...");

    return this.createOutputFiles();
  }

  /**
   * Find assets from node_modules folder and return its path
   * Argument is the path relative to node_modules folder
   */
  findAsset(assetPath) {
    try {
      const path = require.resolve(assetPath);
      return path;
    } catch {
      this.log.error("Could not find where dependencies of apidoc live!");
    }
  }

  createOutputFiles() {
    this.createDir(this.opt.dest);

    // // Write api_data
    // this.fs.writeFileSync(this.opt.dest + './api/data.json', this.api.data + '\n');

    // // Write api_project
    // this.fs.writeFileSync(this.opt.dest + './api/project.json', this.api.project + '\n');

    const api_data = {
      project: JSON.parse(this.api.project),
      data: JSON.parse(this.api.data),
    };

    const api_data_str = JSON.stringify(api_data);

    this.fs.writeFileSync(this.opt.dest + "./api_data.json", api_data_str + "\n");

    // create index.html
    this.fs.writeFileSync(this.path.join(this.opt.dest, 'index.html'), this.getIndexContent());

    // create static folder
    const staticPath = this.path.resolve(this.path.join(this.opt.dest + 'static'));
    this.createDir(staticPath);


    // 将静态文件移动到目录
    this.fs.copySync(this.path.join(this.opt.template, 'static'), staticPath);
  }

  /**
   * Get index.html content as string with placeholder values replaced
   */
  getIndexContent() {
    const projectInfo = JSON.parse(this.api.project);
    const title = projectInfo.title || projectInfo.name || "Loading...";
    const description =
      projectInfo.description || projectInfo.name || "API Documentation";

    const indexHtml = this.fs.readFileSync(
      this.path.join(this.opt.template, "index.html"),
      "utf8"
    );
    return (
      indexHtml
        .toString()
        // replace titles, descriptions and cache busting query params
        .replace(/__API_NAME__/g, title)
        .replace(/__API_DESCRIPTION__/g, description)
        .replace(
          /__API_CACHE_BUSTING_QUERY_PARAM__/g,
          this.cacheBustingQueryParam
        )
    );
  }

  /**
   * Write a JSON file
   *
   * @param {string} dest Destination path
   * @param {string} data Content of the file
   */
  writeJsonFile(dest, data) {
    this.log.verbose(`Writing json file: ${dest}`);
    this.fs.writeFileSync(dest, data + "\n");
  }

  /**
   * Write js file
   *
   * @param {string} dest Destination path
   * @param {string} data Content of the file
   */
  writeJSFile(dest, data) {
    this.log.verbose(`Writing js file: ${dest}`);
    switch (this.opt.mode) {
      case "amd":
      case "es":
        this.fs.writeFileSync(dest, "export default " + data + ";\n");
        break;
      case "commonJS":
        this.fs.writeFileSync(dest, "module.exports = " + data + ";\n");
        break;
      default:
        this.fs.writeFileSync(dest, "define(" + data + ");" + "\n");
    }
  }

  /**
   * Create a directory
   *
   * @param {string} dir Path of the directory to create
   */
  createDir(dir) {
    if (!this.fs.existsSync(dir)) {
      this.log.verbose("Creating dir: " + dir);
      this.fs.mkdirsSync(dir);
    }
  }
}

module.exports = Writer;
